home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 022 / lemacs / buffer.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  16KB  |  493 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. /*
  13.  * Attach a buffer to a window. The
  14.  * values of dot and mark come from the buffer
  15.  * if the use count is 0. Otherwise, they come
  16.  * from some other window.
  17.  */
  18. usebuffer(f, n)
  19. {
  20.         register BUFFER *bp;
  21.         register int    s;
  22.         char            bufn[NBUFN];
  23.  
  24.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  25.                 return (s);
  26.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  27.                 return (FALSE);
  28.     return(swbuffer(bp));
  29. }
  30.  
  31. nextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  32.  
  33. {
  34.         register BUFFER *bp;
  35.         char            bufn[NBUFN];
  36.  
  37.     bp = curbp->b_bufp;
  38.     /* cycle through the buffers to find an eligable one */
  39.     while (bp == NULL | bp->b_flag & BFTEMP) {
  40.         if (bp == NULL)
  41.             bp = bheadp;
  42.         else
  43.             bp = bp->b_bufp;
  44.     }
  45.     return(swbuffer(bp));
  46. }
  47.  
  48. swbuffer(bp)    /* make buffer BP current */
  49.  
  50. BUFFER *bp;
  51.  
  52. {
  53.         register WINDOW *wp;
  54.  
  55.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  56.                 curbp->b_dotp  = curwp->w_dotp;
  57.                 curbp->b_doto  = curwp->w_doto;
  58.                 curbp->b_markp = curwp->w_markp;
  59.                 curbp->b_marko = curwp->w_marko;
  60.         }
  61.         curbp = bp;                             /* Switch.              */
  62.     if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  63.         /* read it in and activate it */
  64.         readin(curbp->b_fname, TRUE);
  65.         curbp->b_dotp = lforw(curbp->b_linep);
  66.         curbp->b_doto = 0;
  67.         curbp->b_active = TRUE;
  68.     }
  69.         curwp->w_bufp  = bp;
  70.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  71.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  72.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  73.                 curwp->w_dotp  = bp->b_dotp;
  74.                 curwp->w_doto  = bp->b_doto;
  75.                 curwp->w_markp = bp->b_markp;
  76.                 curwp->w_marko = bp->b_marko;
  77.                 return (TRUE);
  78.         }
  79.         wp = wheadp;                            /* Look for old.        */
  80.         while (wp != NULL) {
  81.                 if (wp!=curwp && wp->w_bufp==bp) {
  82.                         curwp->w_dotp  = wp->w_dotp;
  83.                         curwp->w_doto  = wp->w_doto;
  84.                         curwp->w_markp = wp->w_markp;
  85.                         curwp->w_marko = wp->w_marko;
  86.                         break;
  87.                 }
  88.                 wp = wp->w_wndp;
  89.         }
  90.         return (TRUE);
  91. }
  92.  
  93. /*
  94.  * Dispose of a buffer, by name.
  95.  * Ask for the name. Look it up (don't get too
  96.  * upset if it isn't there at all!). Get quite upset
  97.  * if the buffer is being displayed. Clear the buffer (ask
  98.  * if the buffer has been changed). Then free the header
  99.  * line and the buffer header. Bound to "C-X K".
  100.  */
  101. killbuffer(f, n)
  102.  
  103. {
  104.     register BUFFER *bp;
  105.         register int    s;
  106.         char bufn[NBUFN];
  107.  
  108.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  109.                 return(s);
  110.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  111.                 return (TRUE);
  112.     return(zotbuf(bp));
  113. }
  114.  
  115. zotbuf(bp)    /* kill the buffer pointed to by bp */
  116.  
  117. register BUFFER *bp;
  118.  
  119. {
  120.         register BUFFER *bp1;
  121.         register BUFFER *bp2;
  122.         register int    s;
  123.  
  124.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  125.                 mlwrite("Buffer is being displayed");
  126.                 return (FALSE);
  127.         }
  128.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  129.                 return (s);
  130.         free((char *) bp->b_linep);             /* Release header line. */
  131.         bp1 = NULL;                             /* Find the header.     */
  132.         bp2 = bheadp;
  133.         while (bp2 != bp) {
  134.                 bp1 = bp2;
  135.                 bp2 = bp2->b_bufp;
  136.         }
  137.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  138.         if (bp1 == NULL)                        /* Unlink it.           */
  139.                 bheadp = bp2;
  140.         else
  141.                 bp1->b_bufp = bp2;
  142.         free((char *) bp);                      /* Release buffer block */
  143.         return (TRUE);
  144. }
  145.  
  146. namebuffer(f,n)        /*    Rename the current buffer    */
  147.  
  148. int f, n;        /* default Flag & Numeric arg */
  149.  
  150. {
  151.     register BUFFER *bp;    /* pointer to scan through all buffers */
  152.     char bufn[NBUFN];    /* buffer to hold buffer name */
  153.  
  154.     /* prompt for and get the new buffer name */
  155. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  156.         return(FALSE);
  157.  
  158.     /* and check for duplicates */
  159.     bp = bheadp;
  160.     while (bp != NULL) {
  161.         if (bp != curbp) {
  162.             /* if the names the same */
  163.             if (strcmp(bufn, bp->b_bname) == 0)
  164.                 goto ask;  /* try again */
  165.         }
  166.         bp = bp->b_bufp;    /* onward */
  167.     }
  168.  
  169.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  170.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  171.     mlerase();
  172. }
  173.  
  174. /*
  175.  * List all of the active
  176.  * buffers. First update the special
  177.  * buffer that holds the list. Next make
  178.  * sure at least 1 window is displaying the
  179.  * buffer list, splitting the screen if this
  180.  * is what it takes. Lastly, repaint all of
  181.  * the windows that are displaying the
  182.  * list. Bound to "C-X C-B".
  183.  */
  184. listbuffers(f, n)
  185. {
  186.         register WINDOW *wp;
  187.         register BUFFER *bp;
  188.         register int    s;
  189.  
  190.         if ((s=makelist()) != TRUE)
  191.                 return (s);
  192.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  193.                 if ((wp=wpopup()) == NULL)
  194.                         return (FALSE);
  195.                 bp = wp->w_bufp;
  196.                 if (--bp->b_nwnd == 0) {
  197.                         bp->b_dotp  = wp->w_dotp;
  198.                         bp->b_doto  = wp->w_doto;
  199.                         bp->b_markp = wp->w_markp;
  200.                         bp->b_marko = wp->w_marko;
  201.                 }
  202.                 wp->w_bufp  = blistp;
  203.                 ++blistp->b_nwnd;
  204.         }
  205.         wp = wheadp;
  206.         while (wp != NULL) {
  207.                 if (wp->w_bufp == blistp) {
  208.                         wp->w_linep = lforw(blistp->b_linep);
  209.                         wp->w_dotp  = lforw(blistp->b_linep);
  210.                         wp->w_doto  = 0;
  211.                         wp->w_markp = NULL;
  212.                         wp->w_marko = 0;
  213.                         wp->w_flag |= WFMODE|WFHARD;
  214.                 }
  215.                 wp = wp->w_wndp;
  216.         }
  217.         return (TRUE);
  218. }
  219.  
  220. /*
  221.  * This routine rebuilds the
  222.  * text in the special secret buffer
  223.  * that holds the buffer list. It is called
  224.  * by the list buffers command. Return TRUE
  225.  * if everything works. Return FALSE if there
  226.  * is an error (if there is no memory).
  227.  */
  228. makelist()
  229. {
  230.         register char   *cp1;
  231.         register char   *cp2;
  232.         register int    c;
  233.         register BUFFER *bp;
  234.         register LINE   *lp;
  235.         register int    nbytes;
  236.         register int    s;
  237.     register int    i;
  238.         register int    type;
  239.         char            b[6+1];
  240.         char            line[128];
  241.  
  242.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  243.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  244.                 return (s);
  245.         strcpy(blistp->b_fname, "");
  246.         if (addline("AC MODES    Size Buffer         File") == FALSE
  247.         ||  addline("-- -----    ---- ------         ----") == FALSE)
  248.                 return (FALSE);
  249.         bp = bheadp;                            /* For all buffers      */
  250.  
  251.     /* build line to report global mode settings */
  252.     cp1 = &line[0];
  253.     *cp1++ = ' ';
  254.     *cp1++ = ' ';
  255.     *cp1++ = ' ';
  256.  
  257.     /* output the mode codes */
  258.     for (i = 0; i < NUMMODES; i++)
  259.         if (gmode & (1 << i))
  260.             *cp1++ = modecode[i];
  261.         else
  262.             *cp1++ = '.';
  263.     strcpy(cp1, "        Global Modes");
  264.     if (addline(line) == FALSE)
  265.         return(FALSE);
  266.  
  267.     /* output the list of buffers */
  268.         while (bp != NULL) {
  269.                 if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones.     */
  270.                         bp = bp->b_bufp;
  271.                         continue;
  272.                 }
  273.                 cp1 = &line[0];                 /* Start at left edge   */
  274.  
  275.         /* output status of ACTIVE flag (has the file been read in? */
  276.                 if (bp->b_active == TRUE)    /* "@" if activated       */
  277.                         *cp1++ = '@';
  278.                 else
  279.                         *cp1++ = ' ';
  280.  
  281.         /* output status of changed flag */
  282.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  283.                         *cp1++ = '*';
  284.                 else
  285.                         *cp1++ = ' ';
  286.                 *cp1++ = ' ';                   /* Gap.                 */
  287.  
  288.         /* output the mode codes */
  289.         for (i = 0; i < NUMMODES; i++) {
  290.             if (bp->b_mode & (1 << i))
  291.                 *cp1++ = modecode[i];
  292.             else
  293.                 *cp1++ = '.';
  294.         }
  295.                 *cp1++ = ' ';                   /* Gap.                 */
  296.                 nbytes = 0;                     /* Count bytes in buf.  */
  297.                 lp = lforw(bp->b_linep);
  298.                 while (lp != bp->b_linep) {
  299.                         nbytes += llength(lp)+1;
  300.                         lp = lforw(lp);
  301.                 }
  302.                 itoa(b, 6, nbytes);             /* 6 digit buffer size. */
  303.                 cp2 = &b[0];
  304.                 while ((c = *cp2++) != 0)
  305.                         *cp1++ = c;
  306.                 *cp1++ = ' ';                   /* Gap.                 */
  307.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  308.                 while ((c = *cp2++) != 0)
  309.                         *cp1++ = c;
  310.                 cp2 = &bp->b_fname[0];          /* File name            */
  311.                 if (*cp2 != 0) {
  312.                         while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  313.                                 *cp1++ = ' ';
  314.                         while ((c = *cp2++) != 0) {
  315.                                 if (cp1 < &line[128-1])
  316.                                         *cp1++ = c;
  317.                         }
  318.                 }
  319.                 *cp1 = 0;                       /* Add to the buffer.   */
  320.                 if (addline(line) == FALSE)
  321.                         return (FALSE);
  322.                 bp = bp->b_bufp;
  323.         }
  324.         return (TRUE);                          /* All done             */
  325. }
  326.  
  327. itoa(buf, width, num)
  328. register char   buf[];
  329. register int    width;
  330. register int    num;
  331. {
  332.         buf[width] = 0;                         /* End of string.       */
  333.         while (num >= 10) {                     /* Conditional digits.  */
  334.                 buf[--width] = (num%10) + '0';
  335.                 num /= 10;
  336.         }
  337.         buf[--width] = num + '0';               /* Always 1 digit.      */
  338.         while (width != 0)                      /* Pad with blanks.     */
  339.                 buf[--width] = ' ';
  340. }
  341.  
  342. /*
  343.  * The argument "text" points to
  344.  * a string. Append this line to the
  345.  * buffer list buffer. Handcraft the EOL
  346.  * on the end. Return TRUE if it worked and
  347.  * FALSE if you ran out of room.
  348.  */
  349. addline(text)
  350. char    *text;
  351. {
  352.         register LINE   *lp;
  353.         register int    i;
  354.         register int    ntext;
  355.  
  356.         ntext = strlen(text);
  357.         if ((lp=lalloc(ntext)) == NULL)
  358.                 return (FALSE);
  359.         for (i=0; i<ntext; ++i)
  360.                 lputc(lp, i, text[i]);
  361.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  362.         lp->l_bp = blistp->b_linep->l_bp;
  363.         blistp->b_linep->l_bp = lp;
  364.         lp->l_fp = blistp->b_linep;
  365.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  366.                 blistp->b_dotp = lp;            /* move it to new line  */
  367.         return (TRUE);
  368. }
  369.  
  370. /*
  371.  * Look through the list of
  372.  * buffers. Return TRUE if there
  373.  * are any changed buffers. Buffers
  374.  * that hold magic internal stuff are
  375.  * not considered; who cares if the
  376.  * list of buffer names is hacked.
  377.  * Return FALSE if no buffers
  378.  * have been changed.
  379.  */
  380. anycb()
  381. {
  382.         register BUFFER *bp;
  383.  
  384.         bp = bheadp;
  385.         while (bp != NULL) {
  386.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  387.                         return (TRUE);
  388.                 bp = bp->b_bufp;
  389.         }
  390.         return (FALSE);
  391. }
  392.  
  393. /*
  394.  * Find a buffer, by name. Return a pointer
  395.  * to the BUFFER structure associated with it. If
  396.  * the named buffer is found, but is a TEMP buffer (like
  397.  * the buffer list) conplain. If the buffer is not found
  398.  * and the "cflag" is TRUE, create it. The "bflag" is
  399.  * the settings for the flags in in buffer.
  400.  */
  401. BUFFER  *
  402. bfind(bname, cflag, bflag)
  403. register char   *bname;
  404. {
  405.         register BUFFER *bp;
  406.     register BUFFER *sb;    /* buffer to insert after */
  407.         register LINE   *lp;
  408.     char *malloc();
  409.  
  410.         bp = bheadp;
  411.         while (bp != NULL) {
  412.                 if (strcmp(bname, bp->b_bname) == 0) {
  413.                         if ((bp->b_flag&BFTEMP) != 0) {
  414.                                 mlwrite("Cannot select builtin buffer");
  415.                                 return (NULL);
  416.                         }
  417.                         return (bp);
  418.                 }
  419.                 bp = bp->b_bufp;
  420.         }
  421.         if (cflag != FALSE) {
  422.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  423.                         return (NULL);
  424.                 if ((lp=lalloc(0)) == NULL) {
  425.                         free((char *) bp);
  426.                         return (NULL);
  427.                 }
  428.         /* find the place in the list to insert this buffer */
  429.         if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  430.             /* insert at the begining */
  431.                     bp->b_bufp = bheadp;
  432.                     bheadp = bp;
  433.             } else {
  434.             sb = bheadp;
  435.             while (sb->b_bufp != NULL) {
  436.                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  437.                     break;
  438.                 sb = sb->b_bufp;
  439.             }
  440.  
  441.             /* and insert it */
  442.                    bp->b_bufp = sb->b_bufp;
  443.                 sb->b_bufp = bp;
  444.                }
  445.  
  446.         /* and set up the other buffer fields */
  447.         bp->b_active = TRUE;
  448.                 bp->b_dotp  = lp;
  449.                 bp->b_doto  = 0;
  450.                 bp->b_markp = NULL;
  451.                 bp->b_marko = 0;
  452.                 bp->b_flag  = bflag;
  453.         bp->b_mode  = gmode;
  454.                 bp->b_nwnd  = 0;
  455.                 bp->b_linep = lp;
  456.                 strcpy(bp->b_fname, "");
  457.                 strcpy(bp->b_bname, bname);
  458.                 lp->l_fp = lp;
  459.                 lp->l_bp = lp;
  460.         }
  461.         return (bp);
  462. }
  463.  
  464. /*
  465.  * This routine blows away all of the text
  466.  * in a buffer. If the buffer is marked as changed
  467.  * then we ask if it is ok to blow it away; this is
  468.  * to save the user the grief of losing text. The
  469.  * window chain is nearly always wrong if this gets
  470.  * called; the caller must arrange for the updates
  471.  * that are required. Return TRUE if everything
  472.  * looks good.
  473.  */
  474. bclear(bp)
  475. register BUFFER *bp;
  476. {
  477.         register LINE   *lp;
  478.         register int    s;
  479.  
  480.         if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  481.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  482.         && (s=mlyesno("Discard changes")) != TRUE)
  483.                 return (s);
  484.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  485.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  486.                 lfree(lp);
  487.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  488.         bp->b_doto  = 0;
  489.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  490.         bp->b_marko = 0;
  491.         return (TRUE);
  492. }
  493.